package com.bluejazz.handler;

import com.bluejazz.controller.response.Result;
import com.bluejazz.controller.response.ResultCode;
import com.bluejazz.exception.OrderException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(OrderException.class)
    public Result<Void> onOrderException(OrderException e) {
        return Result.failure(ResultCode.ORDER_CREATION_FAILED);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<List<String>> onMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return Result.failure(ResultCode.PARAM_IS_INVALID, getValidationMessages(e));
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Result<List<String>> onConstraintViolationException(ConstraintViolationException e) {
        return Result.failure(ResultCode.PARAM_IS_INVALID, getValidationMessages(e.getConstraintViolations()));
    }

    @ExceptionHandler(Exception.class)
    public Result<Void> onGeneralException(Exception e) {
        return Result.failure(ResultCode.SERVER_FAILURE);
    }

    private <T> List<String> getValidationMessages(Set<ConstraintViolation<?>> violations) {
        List<String> errorMsgList = new ArrayList<>();
        for (ConstraintViolation<?> c : violations) {
            errorMsgList.add(c.getMessage());
        }
        return errorMsgList;
    }

    private List<String> getValidationMessages(MethodArgumentNotValidException e) {
        List<String> errorMsgList = new ArrayList<>();
        for (ObjectError error : e.getBindingResult().getAllErrors()) {
            errorMsgList.add(error.getDefaultMessage());
        }
        return errorMsgList;
    }
}
